/*
 * Copyright 2024-2025 The PySCF Developers. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include "pbc.cuh"
#include "int3c2e.cuh"
#include "ft_ao.cuh"

/*
def iter_cart_xyz(n):
    return [(x, y, n-x-y)
            for x in reversed(range(n+1))
            for y in reversed(range(n+1-x))]

dat = []
xyz = [np.array(iter_cart_xyz(li)) for li in range(LMAX+1)]
for li in range(LMAX+1):
    for lj in range(LMAX+1):
        li1 = li + 1
        idx = (xyz[lj][:,None] * li1 + xyz[li]).transpose(2,0,1)
        dat.append(idx.ravel())
pair_idx = np.hstack(dat).astype(np.int32)
pair_offsets = np.cumsum([0] + [x.size for x in dat]).astype(np.int32)

cart_idx = np.hstack([xyz[li].T.ravel() for li in range(LMAX+1)])
*/
__constant__ int16_t c_pair_idx[21168] = { // corresponding to LMAX=6
// (0, 0)
0,0,0,
// (0, 1)
1,0,0,0,1,0,0,0,1,
// (0, 2)
2,1,1,0,0,0,0,1,0,2,1,0,0,0,1,0,1,2,
// (0, 3)
3,2,2,1,1,1,0,0,0,0,0,1,0,2,1,0,3,2,1,0,0,0,1,0,1,2,0,1,2,3,
// (0, 4)
4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,
// (0, 5)
5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,0,0,1,0,1,2,0,1,
2,3,0,1,2,3,4,0,1,2,3,4,5,
// (0, 6)
6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,
5,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,
// (1, 0)
1,0,0,0,1,0,0,0,1,
// (1, 1)
3,2,2,1,0,0,1,0,0,0,1,0,2,3,2,0,1,0,0,0,1,0,0,1,2,2,3,
// (1, 2)
5,4,4,3,2,2,3,2,2,1,0,0,1,0,0,1,0,0,0,1,0,2,3,2,0,1,0,4,5,4,2,3,2,0,1,0,0,0,1,0,0,1,2,2,3,0,0,1,2,2,
3,4,4,5,
// (1, 3)
7,6,6,5,4,4,5,4,4,3,2,2,3,2,2,3,2,2,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,2,3,2,0,1,0,4,5,4,2,3,2,0,1,0,6,7,
6,4,5,4,2,3,2,0,1,0,0,0,1,0,0,1,2,2,3,0,0,1,2,2,3,4,4,5,0,0,1,2,2,3,4,4,5,6,6,7,
// (1, 4)
9,8,8,7,6,6,7,6,6,5,4,4,5,4,4,5,4,4,3,2,2,3,2,2,3,2,2,3,2,2,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,2,3,
2,0,1,0,4,5,4,2,3,2,0,1,0,6,7,6,4,5,4,2,3,2,0,1,0,8,9,8,6,7,6,4,5,4,2,3,2,0,1,0,0,0,1,0,0,1,2,2,3,0,
0,1,2,2,3,4,4,5,0,0,1,2,2,3,4,4,5,6,6,7,0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,
// (1, 5)
11,10,10,9,8,8,9,8,8,7,6,6,7,6,6,7,6,6,5,4,4,5,4,4,5,4,4,5,4,4,3,2,2,3,2,2,3,2,2,3,2,2,3,2,2,1,0,0,1,0,
0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,2,3,2,0,1,0,4,5,4,2,3,2,0,1,0,6,7,6,4,5,4,2,3,2,0,1,0,8,9,8,6,7,6,4,
5,4,2,3,2,0,1,0,10,11,10,8,9,8,6,7,6,4,5,4,2,3,2,0,1,0,0,0,1,0,0,1,2,2,3,0,0,1,2,2,3,4,4,5,0,0,1,2,2,3,
4,4,5,6,6,7,0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,10,10,11,
// (1, 6)
13,12,12,11,10,10,11,10,10,9,8,8,9,8,8,9,8,8,7,6,6,7,6,6,7,6,6,7,6,6,5,4,4,5,4,4,5,4,4,5,4,4,5,4,4,3,2,2,3,2,
2,3,2,2,3,2,2,3,2,2,3,2,2,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,2,3,2,0,1,0,4,5,4,2,3,2,0,
1,0,6,7,6,4,5,4,2,3,2,0,1,0,8,9,8,6,7,6,4,5,4,2,3,2,0,1,0,10,11,10,8,9,8,6,7,6,4,5,4,2,3,2,0,1,0,12,13,12,
10,11,10,8,9,8,6,7,6,4,5,4,2,3,2,0,1,0,0,0,1,0,0,1,2,2,3,0,0,1,2,2,3,4,4,5,0,0,1,2,2,3,4,4,5,6,6,7,0,0,
1,2,2,3,4,4,5,6,6,7,8,8,9,0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,10,10,11,0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,10,10,11,12,
12,13,
// (2, 0)
2,1,1,0,0,0,0,1,0,2,1,0,0,0,1,0,1,2,
// (2, 1)
5,4,4,3,3,3,2,1,1,0,0,0,2,1,1,0,0,0,0,1,0,2,1,0,3,4,3,5,4,3,0,1,0,2,1,0,0,0,1,0,1,2,0,0,1,0,1,2,3,3,
4,3,4,5,
// (2, 2)
8,7,7,6,6,6,5,4,4,3,3,3,5,4,4,3,3,3,2,1,1,0,0,0,2,1,1,0,0,0,2,1,1,0,0,0,0,1,0,2,1,0,3,4,3,5,4,3,0,1,
0,2,1,0,6,7,6,8,7,6,3,4,3,5,4,3,0,1,0,2,1,0,0,0,1,0,1,2,0,0,1,0,1,2,3,3,4,3,4,5,0,0,1,0,1,2,3,3,4,3,
4,5,6,6,7,6,7,8,
// (2, 3)
11,10,10,9,9,9,8,7,7,6,6,6,8,7,7,6,6,6,5,4,4,3,3,3,5,4,4,3,3,3,5,4,4,3,3,3,2,1,1,0,0,0,2,1,1,0,0,0,2,1,
1,0,0,0,2,1,1,0,0,0,0,1,0,2,1,0,3,4,3,5,4,3,0,1,0,2,1,0,6,7,6,8,7,6,3,4,3,5,4,3,0,1,0,2,1,0,9,10,9,11,
10,9,6,7,6,8,7,6,3,4,3,5,4,3,0,1,0,2,1,0,0,0,1,0,1,2,0,0,1,0,1,2,3,3,4,3,4,5,0,0,1,0,1,2,3,3,4,3,4,5,
6,6,7,6,7,8,0,0,1,0,1,2,3,3,4,3,4,5,6,6,7,6,7,8,9,9,10,9,10,11,
// (2, 4)
14,13,13,12,12,12,11,10,10,9,9,9,11,10,10,9,9,9,8,7,7,6,6,6,8,7,7,6,6,6,8,7,7,6,6,6,5,4,4,3,3,3,5,4,4,3,3,3,5,4,
4,3,3,3,5,4,4,3,3,3,2,1,1,0,0,0,2,1,1,0,0,0,2,1,1,0,0,0,2,1,1,0,0,0,2,1,1,0,0,0,0,1,0,2,1,0,3,4,3,5,
4,3,0,1,0,2,1,0,6,7,6,8,7,6,3,4,3,5,4,3,0,1,0,2,1,0,9,10,9,11,10,9,6,7,6,8,7,6,3,4,3,5,4,3,0,1,0,2,1,0,
12,13,12,14,13,12,9,10,9,11,10,9,6,7,6,8,7,6,3,4,3,5,4,3,0,1,0,2,1,0,0,0,1,0,1,2,0,0,1,0,1,2,3,3,4,3,4,5,0,0,
1,0,1,2,3,3,4,3,4,5,6,6,7,6,7,8,0,0,1,0,1,2,3,3,4,3,4,5,6,6,7,6,7,8,9,9,10,9,10,11,0,0,1,0,1,2,3,3,4,3,
4,5,6,6,7,6,7,8,9,9,10,9,10,11,12,12,13,12,13,14,
// (2, 5)
17,16,16,15,15,15,14,13,13,12,12,12,14,13,13,12,12,12,11,10,10,9,9,9,11,10,10,9,9,9,11,10,10,9,9,9,8,7,7,6,6,6,8,7,7,6,6,6,8,7,
7,6,6,6,8,7,7,6,6,6,5,4,4,3,3,3,5,4,4,3,3,3,5,4,4,3,3,3,5,4,4,3,3,3,5,4,4,3,3,3,2,1,1,0,0,0,2,1,1,0,
0,0,2,1,1,0,0,0,2,1,1,0,0,0,2,1,1,0,0,0,2,1,1,0,0,0,0,1,0,2,1,0,3,4,3,5,4,3,0,1,0,2,1,0,6,7,6,8,7,6,
3,4,3,5,4,3,0,1,0,2,1,0,9,10,9,11,10,9,6,7,6,8,7,6,3,4,3,5,4,3,0,1,0,2,1,0,12,13,12,14,13,12,9,10,9,11,10,9,6,7,
6,8,7,6,3,4,3,5,4,3,0,1,0,2,1,0,15,16,15,17,16,15,12,13,12,14,13,12,9,10,9,11,10,9,6,7,6,8,7,6,3,4,3,5,4,3,0,1,0,2,
1,0,0,0,1,0,1,2,0,0,1,0,1,2,3,3,4,3,4,5,0,0,1,0,1,2,3,3,4,3,4,5,6,6,7,6,7,8,0,0,1,0,1,2,3,3,4,3,4,5,
6,6,7,6,7,8,9,9,10,9,10,11,0,0,1,0,1,2,3,3,4,3,4,5,6,6,7,6,7,8,9,9,10,9,10,11,12,12,13,12,13,14,0,0,1,0,1,2,3,3,
4,3,4,5,6,6,7,6,7,8,9,9,10,9,10,11,12,12,13,12,13,14,15,15,16,15,16,17,
// (2, 6)
20,19,19,18,18,18,17,16,16,15,15,15,17,16,16,15,15,15,14,13,13,12,12,12,14,13,13,12,12,12,14,13,13,12,12,12,11,10,10,9,9,9,11,10,10,9,9,9,11,10,
10,9,9,9,11,10,10,9,9,9,8,7,7,6,6,6,8,7,7,6,6,6,8,7,7,6,6,6,8,7,7,6,6,6,8,7,7,6,6,6,5,4,4,3,3,3,5,4,4,3,
3,3,5,4,4,3,3,3,5,4,4,3,3,3,5,4,4,3,3,3,5,4,4,3,3,3,2,1,1,0,0,0,2,1,1,0,0,0,2,1,1,0,0,0,2,1,1,0,0,0,
2,1,1,0,0,0,2,1,1,0,0,0,2,1,1,0,0,0,0,1,0,2,1,0,3,4,3,5,4,3,0,1,0,2,1,0,6,7,6,8,7,6,3,4,3,5,4,3,0,1,
0,2,1,0,9,10,9,11,10,9,6,7,6,8,7,6,3,4,3,5,4,3,0,1,0,2,1,0,12,13,12,14,13,12,9,10,9,11,10,9,6,7,6,8,7,6,3,4,3,5,
4,3,0,1,0,2,1,0,15,16,15,17,16,15,12,13,12,14,13,12,9,10,9,11,10,9,6,7,6,8,7,6,3,4,3,5,4,3,0,1,0,2,1,0,18,19,18,20,19,18,
15,16,15,17,16,15,12,13,12,14,13,12,9,10,9,11,10,9,6,7,6,8,7,6,3,4,3,5,4,3,0,1,0,2,1,0,0,0,1,0,1,2,0,0,1,0,1,2,3,3,
4,3,4,5,0,0,1,0,1,2,3,3,4,3,4,5,6,6,7,6,7,8,0,0,1,0,1,2,3,3,4,3,4,5,6,6,7,6,7,8,9,9,10,9,10,11,0,0,1,0,
1,2,3,3,4,3,4,5,6,6,7,6,7,8,9,9,10,9,10,11,12,12,13,12,13,14,0,0,1,0,1,2,3,3,4,3,4,5,6,6,7,6,7,8,9,9,10,9,10,11,
12,12,13,12,13,14,15,15,16,15,16,17,0,0,1,0,1,2,3,3,4,3,4,5,6,6,7,6,7,8,9,9,10,9,10,11,12,12,13,12,13,14,15,15,16,15,16,17,18,18,
19,18,19,20,
// (3, 0)
3,2,2,1,1,1,0,0,0,0,0,1,0,2,1,0,3,2,1,0,0,0,1,0,1,2,0,1,2,3,
// (3, 1)
7,6,6,5,5,5,4,4,4,4,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,5,4,6,5,4,7,6,5,4,
0,1,0,2,1,0,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,
// (3, 2)
11,10,10,9,9,9,8,8,8,8,7,6,6,5,5,5,4,4,4,4,7,6,6,5,5,5,4,4,4,4,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,
3,2,2,1,1,1,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,8,9,8,10,9,8,11,10,9,8,
4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,
0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,8,8,9,8,9,10,8,9,10,11,
// (3, 3)
15,14,14,13,13,13,12,12,12,12,11,10,10,9,9,9,8,8,8,8,11,10,10,9,9,9,8,8,8,8,7,6,6,5,5,5,4,4,4,4,7,6,6,5,5,5,4,4,4,4,
7,6,6,5,5,5,4,4,4,4,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,
0,1,0,2,1,0,3,2,1,0,4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,8,9,8,10,9,8,11,10,9,8,4,5,4,6,5,4,7,6,5,4,
0,1,0,2,1,0,3,2,1,0,12,13,12,14,13,12,15,14,13,12,8,9,8,10,9,8,11,10,9,8,4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,
0,0,1,0,1,2,0,1,2,3,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,
8,8,9,8,9,10,8,9,10,11,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,8,8,9,8,9,10,8,9,10,11,12,12,13,12,13,14,12,13,14,15,
// (3, 4)
19,18,18,17,17,17,16,16,16,16,15,14,14,13,13,13,12,12,12,12,15,14,14,13,13,13,12,12,12,12,11,10,10,9,9,9,8,8,8,8,11,10,10,9,9,9,8,8,8,8,
11,10,10,9,9,9,8,8,8,8,7,6,6,5,5,5,4,4,4,4,7,6,6,5,5,5,4,4,4,4,7,6,6,5,5,5,4,4,4,4,7,6,6,5,5,5,4,4,4,4,
3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,
0,1,0,2,1,0,3,2,1,0,4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,8,9,8,10,9,8,11,10,9,8,4,5,4,6,5,4,7,6,5,4,
0,1,0,2,1,0,3,2,1,0,12,13,12,14,13,12,15,14,13,12,8,9,8,10,9,8,11,10,9,8,4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,
16,17,16,18,17,16,19,18,17,16,12,13,12,14,13,12,15,14,13,12,8,9,8,10,9,8,11,10,9,8,4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,
0,0,1,0,1,2,0,1,2,3,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,
8,8,9,8,9,10,8,9,10,11,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,8,8,9,8,9,10,8,9,10,11,12,12,13,12,13,14,12,13,14,15,
0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,8,8,9,8,9,10,8,9,10,11,12,12,13,12,13,14,12,13,14,15,16,16,17,16,17,18,16,17,18,19,
// (3, 5)
23,22,22,21,21,21,20,20,20,20,19,18,18,17,17,17,16,16,16,16,19,18,18,17,17,17,16,16,16,16,15,14,14,13,13,13,12,12,12,12,15,14,14,13,13,13,12,12,12,12,
15,14,14,13,13,13,12,12,12,12,11,10,10,9,9,9,8,8,8,8,11,10,10,9,9,9,8,8,8,8,11,10,10,9,9,9,8,8,8,8,11,10,10,9,9,9,8,8,8,8,
7,6,6,5,5,5,4,4,4,4,7,6,6,5,5,5,4,4,4,4,7,6,6,5,5,5,4,4,4,4,7,6,6,5,5,5,4,4,4,4,7,6,6,5,5,5,4,4,4,4,
3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,
3,2,2,1,1,1,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,8,9,8,10,9,8,11,10,9,8,
4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,12,13,12,14,13,12,15,14,13,12,8,9,8,10,9,8,11,10,9,8,4,5,4,6,5,4,7,6,5,4,
0,1,0,2,1,0,3,2,1,0,16,17,16,18,17,16,19,18,17,16,12,13,12,14,13,12,15,14,13,12,8,9,8,10,9,8,11,10,9,8,4,5,4,6,5,4,7,6,5,4,
0,1,0,2,1,0,3,2,1,0,20,21,20,22,21,20,23,22,21,20,16,17,16,18,17,16,19,18,17,16,12,13,12,14,13,12,15,14,13,12,8,9,8,10,9,8,11,10,9,8,
4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,
0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,8,8,9,8,9,10,8,9,10,11,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,
8,8,9,8,9,10,8,9,10,11,12,12,13,12,13,14,12,13,14,15,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,8,8,9,8,9,10,8,9,10,11,
12,12,13,12,13,14,12,13,14,15,16,16,17,16,17,18,16,17,18,19,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,8,8,9,8,9,10,8,9,10,11,
12,12,13,12,13,14,12,13,14,15,16,16,17,16,17,18,16,17,18,19,20,20,21,20,21,22,20,21,22,23,
// (3, 6)
27,26,26,25,25,25,24,24,24,24,23,22,22,21,21,21,20,20,20,20,23,22,22,21,21,21,20,20,20,20,19,18,18,17,17,17,16,16,16,16,19,18,18,17,17,17,16,16,16,16,
19,18,18,17,17,17,16,16,16,16,15,14,14,13,13,13,12,12,12,12,15,14,14,13,13,13,12,12,12,12,15,14,14,13,13,13,12,12,12,12,15,14,14,13,13,13,12,12,12,12,
11,10,10,9,9,9,8,8,8,8,11,10,10,9,9,9,8,8,8,8,11,10,10,9,9,9,8,8,8,8,11,10,10,9,9,9,8,8,8,8,11,10,10,9,9,9,8,8,8,8,
7,6,6,5,5,5,4,4,4,4,7,6,6,5,5,5,4,4,4,4,7,6,6,5,5,5,4,4,4,4,7,6,6,5,5,5,4,4,4,4,7,6,6,5,5,5,4,4,4,4,
7,6,6,5,5,5,4,4,4,4,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,
3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,3,2,2,1,1,1,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,5,4,6,5,4,7,6,5,4,
0,1,0,2,1,0,3,2,1,0,8,9,8,10,9,8,11,10,9,8,4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,12,13,12,14,13,12,15,14,13,12,
8,9,8,10,9,8,11,10,9,8,4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,16,17,16,18,17,16,19,18,17,16,12,13,12,14,13,12,15,14,13,12,
8,9,8,10,9,8,11,10,9,8,4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,20,21,20,22,21,20,23,22,21,20,16,17,16,18,17,16,19,18,17,16,
12,13,12,14,13,12,15,14,13,12,8,9,8,10,9,8,11,10,9,8,4,5,4,6,5,4,7,6,5,4,0,1,0,2,1,0,3,2,1,0,24,25,24,26,25,24,27,26,25,24,
20,21,20,22,21,20,23,22,21,20,16,17,16,18,17,16,19,18,17,16,12,13,12,14,13,12,15,14,13,12,8,9,8,10,9,8,11,10,9,8,4,5,4,6,5,4,7,6,5,4,
0,1,0,2,1,0,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,0,0,1,0,1,2,0,1,2,3,
4,4,5,4,5,6,4,5,6,7,8,8,9,8,9,10,8,9,10,11,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,8,8,9,8,9,10,8,9,10,11,
12,12,13,12,13,14,12,13,14,15,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,8,8,9,8,9,10,8,9,10,11,12,12,13,12,13,14,12,13,14,15,
16,16,17,16,17,18,16,17,18,19,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,8,8,9,8,9,10,8,9,10,11,12,12,13,12,13,14,12,13,14,15,
16,16,17,16,17,18,16,17,18,19,20,20,21,20,21,22,20,21,22,23,0,0,1,0,1,2,0,1,2,3,4,4,5,4,5,6,4,5,6,7,8,8,9,8,9,10,8,9,10,11,
12,12,13,12,13,14,12,13,14,15,16,16,17,16,17,18,16,17,18,19,20,20,21,20,21,22,20,21,22,23,24,24,25,24,25,26,24,25,26,27,
// (4, 0)
4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,
// (4, 1)
9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,0,1,0,2,1,
0,3,2,1,0,4,3,2,1,0,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,
0,1,2,3,4,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,
// (4, 2)
14,13,13,12,12,12,11,11,11,11,10,10,10,10,10,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,4,3,3,2,2,
2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,
4,3,2,1,0,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,10,11,10,12,11,10,13,12,11,10,14,13,12,11,10,
5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,0,1,0,1,
2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,
5,6,7,8,9,10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,
// (4, 3)
19,18,18,17,17,17,16,16,16,16,15,15,15,15,15,14,13,13,12,12,12,11,11,11,11,10,10,10,10,10,14,13,13,12,12,12,11,11,11,11,10,10,10,10,10,9,8,8,7,7,
7,6,6,6,6,5,5,5,5,5,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,4,3,3,2,2,2,1,1,1,1,
0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,
0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,10,11,10,12,11,
10,13,12,11,10,14,13,12,11,10,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,15,16,15,17,16,15,18,17,16,15,
19,18,17,16,15,10,11,10,12,11,10,13,12,11,10,14,13,12,11,10,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,
0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,0,0,1,0,1,
2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,0,0,1,0,1,2,0,1,2,3,
0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,15,15,16,15,16,17,15,16,17,18,15,16,17,18,19,
// (4, 4)
24,23,23,22,22,22,21,21,21,21,20,20,20,20,20,19,18,18,17,17,17,16,16,16,16,15,15,15,15,15,19,18,18,17,17,17,16,16,16,16,15,15,15,15,15,14,13,13,12,12,
12,11,11,11,11,10,10,10,10,10,14,13,13,12,12,12,11,11,11,11,10,10,10,10,10,14,13,13,12,12,12,11,11,11,11,10,10,10,10,10,9,8,8,7,7,7,6,6,6,6,
5,5,5,5,5,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,
4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,
2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,6,5,7,6,5,8,7,6,5,
9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,10,11,10,12,11,10,13,12,11,10,14,13,12,11,10,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,
0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,15,16,15,17,16,15,18,17,16,15,19,18,17,16,15,10,11,10,12,11,10,13,12,11,10,14,13,12,11,10,5,6,5,7,6,
5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,20,21,20,22,21,20,23,22,21,20,24,23,22,21,20,15,16,15,17,16,15,18,17,16,15,
19,18,17,16,15,10,11,10,12,11,10,13,12,11,10,14,13,12,11,10,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,
0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,0,0,1,0,1,
2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,0,0,1,0,1,2,0,1,2,3,
0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,15,15,16,15,16,17,15,16,17,18,15,16,17,18,19,
0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,15,15,16,15,16,
17,15,16,17,18,15,16,17,18,19,20,20,21,20,21,22,20,21,22,23,20,21,22,23,24,
// (4, 5)
29,28,28,27,27,27,26,26,26,26,25,25,25,25,25,24,23,23,22,22,22,21,21,21,21,20,20,20,20,20,24,23,23,22,22,22,21,21,21,21,20,20,20,20,20,19,18,18,17,17,
17,16,16,16,16,15,15,15,15,15,19,18,18,17,17,17,16,16,16,16,15,15,15,15,15,19,18,18,17,17,17,16,16,16,16,15,15,15,15,15,14,13,13,12,12,12,11,11,11,11,
10,10,10,10,10,14,13,13,12,12,12,11,11,11,11,10,10,10,10,10,14,13,13,12,12,12,11,11,11,11,10,10,10,10,10,14,13,13,12,12,12,11,11,11,11,10,10,10,10,10,
9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,9,8,8,7,7,
7,6,6,6,6,5,5,5,5,5,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,
0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,
4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,
0,3,2,1,0,4,3,2,1,0,10,11,10,12,11,10,13,12,11,10,14,13,12,11,10,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,
4,3,2,1,0,15,16,15,17,16,15,18,17,16,15,19,18,17,16,15,10,11,10,12,11,10,13,12,11,10,14,13,12,11,10,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,
0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,20,21,20,22,21,20,23,22,21,20,24,23,22,21,20,15,16,15,17,16,15,18,17,16,15,19,18,17,16,15,10,11,10,12,11,
10,13,12,11,10,14,13,12,11,10,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,25,26,25,27,26,25,28,27,26,25,
29,28,27,26,25,20,21,20,22,21,20,23,22,21,20,24,23,22,21,20,15,16,15,17,16,15,18,17,16,15,19,18,17,16,15,10,11,10,12,11,10,13,12,11,10,14,13,12,11,10,
5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,0,1,0,1,
2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,
5,6,7,8,9,10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,
10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,15,15,16,15,16,17,15,16,17,18,15,16,17,18,19,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,
7,5,6,7,8,5,6,7,8,9,10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,15,15,16,15,16,17,15,16,17,18,15,16,17,18,19,20,20,21,20,21,22,20,21,22,23,
20,21,22,23,24,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,
15,15,16,15,16,17,15,16,17,18,15,16,17,18,19,20,20,21,20,21,22,20,21,22,23,20,21,22,23,24,25,25,26,25,26,27,25,26,27,28,25,26,27,28,29,
// (4, 6)
34,33,33,32,32,32,31,31,31,31,30,30,30,30,30,29,28,28,27,27,27,26,26,26,26,25,25,25,25,25,29,28,28,27,27,27,26,26,26,26,25,25,25,25,25,24,23,23,22,22,
22,21,21,21,21,20,20,20,20,20,24,23,23,22,22,22,21,21,21,21,20,20,20,20,20,24,23,23,22,22,22,21,21,21,21,20,20,20,20,20,19,18,18,17,17,17,16,16,16,16,
15,15,15,15,15,19,18,18,17,17,17,16,16,16,16,15,15,15,15,15,19,18,18,17,17,17,16,16,16,16,15,15,15,15,15,19,18,18,17,17,17,16,16,16,16,15,15,15,15,15,
14,13,13,12,12,12,11,11,11,11,10,10,10,10,10,14,13,13,12,12,12,11,11,11,11,10,10,10,10,10,14,13,13,12,12,12,11,11,11,11,10,10,10,10,10,14,13,13,12,12,
12,11,11,11,11,10,10,10,10,10,14,13,13,12,12,12,11,11,11,11,10,10,10,10,10,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,9,8,8,7,7,7,6,6,6,6,
5,5,5,5,5,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,
9,8,8,7,7,7,6,6,6,6,5,5,5,5,5,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,
2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,
0,0,0,0,0,4,3,3,2,2,2,1,1,1,1,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,
0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,10,11,10,12,11,10,13,12,11,10,14,13,12,11,10,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,
0,3,2,1,0,4,3,2,1,0,15,16,15,17,16,15,18,17,16,15,19,18,17,16,15,10,11,10,12,11,10,13,12,11,10,14,13,12,11,10,5,6,5,7,6,5,8,7,6,5,
9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,20,21,20,22,21,20,23,22,21,20,24,23,22,21,20,15,16,15,17,16,15,18,17,16,15,19,18,17,16,15,
10,11,10,12,11,10,13,12,11,10,14,13,12,11,10,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,25,26,25,27,26,
25,28,27,26,25,29,28,27,26,25,20,21,20,22,21,20,23,22,21,20,24,23,22,21,20,15,16,15,17,16,15,18,17,16,15,19,18,17,16,15,10,11,10,12,11,10,13,12,11,10,
14,13,12,11,10,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,30,31,30,32,31,30,33,32,31,30,34,33,32,31,30,
25,26,25,27,26,25,28,27,26,25,29,28,27,26,25,20,21,20,22,21,20,23,22,21,20,24,23,22,21,20,15,16,15,17,16,15,18,17,16,15,19,18,17,16,15,10,11,10,12,11,
10,13,12,11,10,14,13,12,11,10,5,6,5,7,6,5,8,7,6,5,9,8,7,6,5,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,
0,1,2,3,4,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,
5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,
7,5,6,7,8,5,6,7,8,9,10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,15,15,16,15,16,17,15,16,17,18,15,16,17,18,19,0,0,1,0,1,2,0,1,2,3,
0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,15,15,16,15,16,17,15,16,17,18,15,16,17,18,19,
20,20,21,20,21,22,20,21,22,23,20,21,22,23,24,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,10,10,11,10,11,
12,10,11,12,13,10,11,12,13,14,15,15,16,15,16,17,15,16,17,18,15,16,17,18,19,20,20,21,20,21,22,20,21,22,23,20,21,22,23,24,25,25,26,25,26,27,25,26,27,28,
25,26,27,28,29,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,5,5,6,5,6,7,5,6,7,8,5,6,7,8,9,10,10,11,10,11,12,10,11,12,13,10,11,12,13,14,
15,15,16,15,16,17,15,16,17,18,15,16,17,18,19,20,20,21,20,21,22,20,21,22,23,20,21,22,23,24,25,25,26,25,26,27,25,26,27,28,25,26,27,28,29,30,30,31,30,31,
32,30,31,32,33,30,31,32,33,34,
// (5, 0)
5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,0,0,1,0,1,2,0,1,
2,3,0,1,2,3,4,0,1,2,3,4,5,
// (5, 1)
11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,
2,2,1,1,1,1,1,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,
10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,0,1,
0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,
// (5, 2)
17,16,16,15,15,15,14,14,14,14,13,13,13,13,13,12,12,12,12,12,12,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,11,10,10,9,9,9,8,8,
8,8,7,7,7,7,7,6,6,6,6,6,6,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,
0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,7,6,
8,7,6,9,8,7,6,10,9,8,7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,12,13,12,14,13,12,15,14,13,12,16,
15,14,13,12,17,16,15,14,13,12,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,
1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,
6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,
10,6,7,8,9,10,11,12,12,13,12,13,14,12,13,14,15,12,13,14,15,16,12,13,14,15,16,17,
// (5, 3)
23,22,22,21,21,21,20,20,20,20,19,19,19,19,19,18,18,18,18,18,18,17,16,16,15,15,15,14,14,14,14,13,13,13,13,13,12,12,12,12,12,12,17,16,16,15,15,15,14,14,
14,14,13,13,13,13,13,12,12,12,12,12,12,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,
6,6,6,6,6,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,
3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,
1,1,1,1,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,10,9,8,
7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,12,13,12,14,13,12,15,14,13,12,16,15,14,13,12,17,16,15,14,13,12,6,7,6,8,7,6,
9,8,7,6,10,9,8,7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,18,19,18,20,19,18,21,20,19,18,22,21,20,19,
18,23,22,21,20,19,18,12,13,12,14,13,12,15,14,13,12,16,15,14,13,12,17,16,15,14,13,12,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,10,9,8,7,6,0,
1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,0,1,0,1,2,0,1,2,
3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,
2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,12,12,13,12,13,14,12,13,14,15,12,13,14,15,16,12,13,14,15,16,17,0,0,1,0,
1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,12,12,13,12,13,14,12,13,14,15,12,13,
14,15,16,12,13,14,15,16,17,18,18,19,18,19,20,18,19,20,21,18,19,20,21,22,18,19,20,21,22,23,
// (5, 4)
29,28,28,27,27,27,26,26,26,26,25,25,25,25,25,24,24,24,24,24,24,23,22,22,21,21,21,20,20,20,20,19,19,19,19,19,18,18,18,18,18,18,23,22,22,21,21,21,20,20,
20,20,19,19,19,19,19,18,18,18,18,18,18,17,16,16,15,15,15,14,14,14,14,13,13,13,13,13,12,12,12,12,12,12,17,16,16,15,15,15,14,14,14,14,13,13,13,13,13,12,
12,12,12,12,12,17,16,16,15,15,15,14,14,14,14,13,13,13,13,13,12,12,12,12,12,12,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,11,10,10,
9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,11,10,10,9,9,9,8,8,8,8,7,
7,7,7,7,6,6,6,6,6,6,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,
0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,
2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,7,6,8,7,6,9,8,7,6,10,9,8,7,
6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,12,13,12,14,13,12,15,14,13,12,16,15,14,13,12,17,16,15,14,13,12,6,
7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,18,19,18,20,19,18,21,20,19,
18,22,21,20,19,18,23,22,21,20,19,18,12,13,12,14,13,12,15,14,13,12,16,15,14,13,12,17,16,15,14,13,12,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,10,
9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,24,25,24,26,25,24,27,26,25,24,28,27,26,25,24,29,28,27,26,25,24,18,19,18,20,
19,18,21,20,19,18,22,21,20,19,18,23,22,21,20,19,18,12,13,12,14,13,12,15,14,13,12,16,15,14,13,12,17,16,15,14,13,12,6,7,6,8,7,6,9,8,7,6,10,9,
8,7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,
5,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,0,0,1,0,1,2,0,
1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,12,12,13,12,13,14,12,13,14,15,12,13,14,15,16,
12,13,14,15,16,17,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,12,12,
13,12,13,14,12,13,14,15,12,13,14,15,16,12,13,14,15,16,17,18,18,19,18,19,20,18,19,20,21,18,19,20,21,22,18,19,20,21,22,23,0,0,1,0,1,2,0,1,2,3,
0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,12,12,13,12,13,14,12,13,14,15,12,13,14,15,16,12,13,14,
15,16,17,18,18,19,18,19,20,18,19,20,21,18,19,20,21,22,18,19,20,21,22,23,24,24,25,24,25,26,24,25,26,27,24,25,26,27,28,24,25,26,27,28,29,
// (5, 5)
35,34,34,33,33,33,32,32,32,32,31,31,31,31,31,30,30,30,30,30,30,29,28,28,27,27,27,26,26,26,26,25,25,25,25,25,24,24,24,24,24,24,29,28,28,27,27,27,26,26,
26,26,25,25,25,25,25,24,24,24,24,24,24,23,22,22,21,21,21,20,20,20,20,19,19,19,19,19,18,18,18,18,18,18,23,22,22,21,21,21,20,20,20,20,19,19,19,19,19,18,
18,18,18,18,18,23,22,22,21,21,21,20,20,20,20,19,19,19,19,19,18,18,18,18,18,18,17,16,16,15,15,15,14,14,14,14,13,13,13,13,13,12,12,12,12,12,12,17,16,16,
15,15,15,14,14,14,14,13,13,13,13,13,12,12,12,12,12,12,17,16,16,15,15,15,14,14,14,14,13,13,13,13,13,12,12,12,12,12,12,17,16,16,15,15,15,14,14,14,14,13,
13,13,13,13,12,12,12,12,12,12,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,
6,6,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,11,10,10,9,9,9,
8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,
1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,
4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,
0,4,3,2,1,0,5,4,3,2,1,0,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,
3,2,1,0,12,13,12,14,13,12,15,14,13,12,16,15,14,13,12,17,16,15,14,13,12,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,10,9,8,7,6,0,1,0,2,
1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,18,19,18,20,19,18,21,20,19,18,22,21,20,19,18,23,22,21,20,19,18,12,13,12,14,13,12,15,14,13,12,16,15,
14,13,12,17,16,15,14,13,12,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,
0,24,25,24,26,25,24,27,26,25,24,28,27,26,25,24,29,28,27,26,25,24,18,19,18,20,19,18,21,20,19,18,22,21,20,19,18,23,22,21,20,19,18,12,13,12,14,13,12,15,
14,13,12,16,15,14,13,12,17,16,15,14,13,12,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,
5,4,3,2,1,0,30,31,30,32,31,30,33,32,31,30,34,33,32,31,30,35,34,33,32,31,30,24,25,24,26,25,24,27,26,25,24,28,27,26,25,24,29,28,27,26,25,24,18,19,
18,20,19,18,21,20,19,18,22,21,20,19,18,23,22,21,20,19,18,12,13,12,14,13,12,15,14,13,12,16,15,14,13,12,17,16,15,14,13,12,6,7,6,8,7,6,9,8,7,6,
10,9,8,7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,
3,4,5,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,0,0,1,0,1,
2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,12,12,13,12,13,14,12,13,14,15,12,13,14,
15,16,12,13,14,15,16,17,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,
12,12,13,12,13,14,12,13,14,15,12,13,14,15,16,12,13,14,15,16,17,18,18,19,18,19,20,18,19,20,21,18,19,20,21,22,18,19,20,21,22,23,0,0,1,0,1,2,0,1,
2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,12,12,13,12,13,14,12,13,14,15,12,13,14,15,16,12,
13,14,15,16,17,18,18,19,18,19,20,18,19,20,21,18,19,20,21,22,18,19,20,21,22,23,24,24,25,24,25,26,24,25,26,27,24,25,26,27,28,24,25,26,27,28,29,0,0,1,
0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,12,12,13,12,13,14,12,13,14,15,12,
13,14,15,16,12,13,14,15,16,17,18,18,19,18,19,20,18,19,20,21,18,19,20,21,22,18,19,20,21,22,23,24,24,25,24,25,26,24,25,26,27,24,25,26,27,28,24,25,26,27,
28,29,30,30,31,30,31,32,30,31,32,33,30,31,32,33,34,30,31,32,33,34,35,
// (5, 6)
41,40,40,39,39,39,38,38,38,38,37,37,37,37,37,36,36,36,36,36,36,35,34,34,33,33,33,32,32,32,32,31,31,31,31,31,30,30,30,30,30,30,35,34,34,33,33,33,32,32,
32,32,31,31,31,31,31,30,30,30,30,30,30,29,28,28,27,27,27,26,26,26,26,25,25,25,25,25,24,24,24,24,24,24,29,28,28,27,27,27,26,26,26,26,25,25,25,25,25,24,
24,24,24,24,24,29,28,28,27,27,27,26,26,26,26,25,25,25,25,25,24,24,24,24,24,24,23,22,22,21,21,21,20,20,20,20,19,19,19,19,19,18,18,18,18,18,18,23,22,22,
21,21,21,20,20,20,20,19,19,19,19,19,18,18,18,18,18,18,23,22,22,21,21,21,20,20,20,20,19,19,19,19,19,18,18,18,18,18,18,23,22,22,21,21,21,20,20,20,20,19,
19,19,19,19,18,18,18,18,18,18,17,16,16,15,15,15,14,14,14,14,13,13,13,13,13,12,12,12,12,12,12,17,16,16,15,15,15,14,14,14,14,13,13,13,13,13,12,12,12,12,
12,12,17,16,16,15,15,15,14,14,14,14,13,13,13,13,13,12,12,12,12,12,12,17,16,16,15,15,15,14,14,14,14,13,13,13,13,13,12,12,12,12,12,12,17,16,16,15,15,15,
14,14,14,14,13,13,13,13,13,12,12,12,12,12,12,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,11,10,10,9,9,9,8,8,8,8,7,7,7,7,
7,6,6,6,6,6,6,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,11,
10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,11,10,10,9,9,9,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,5,4,4,3,3,3,2,2,2,
2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,
0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,
3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,5,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,
2,1,0,5,4,3,2,1,0,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,
0,12,13,12,14,13,12,15,14,13,12,16,15,14,13,12,17,16,15,14,13,12,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,
2,1,0,4,3,2,1,0,5,4,3,2,1,0,18,19,18,20,19,18,21,20,19,18,22,21,20,19,18,23,22,21,20,19,18,12,13,12,14,13,12,15,14,13,12,16,15,14,13,12,
17,16,15,14,13,12,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,24,25,
24,26,25,24,27,26,25,24,28,27,26,25,24,29,28,27,26,25,24,18,19,18,20,19,18,21,20,19,18,22,21,20,19,18,23,22,21,20,19,18,12,13,12,14,13,12,15,14,13,12,
16,15,14,13,12,17,16,15,14,13,12,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,
2,1,0,30,31,30,32,31,30,33,32,31,30,34,33,32,31,30,35,34,33,32,31,30,24,25,24,26,25,24,27,26,25,24,28,27,26,25,24,29,28,27,26,25,24,18,19,18,20,19,
18,21,20,19,18,22,21,20,19,18,23,22,21,20,19,18,12,13,12,14,13,12,15,14,13,12,16,15,14,13,12,17,16,15,14,13,12,6,7,6,8,7,6,9,8,7,6,10,9,8,
7,6,11,10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,36,37,36,38,37,36,39,38,37,36,40,39,38,37,36,41,40,39,38,37,36,
30,31,30,32,31,30,33,32,31,30,34,33,32,31,30,35,34,33,32,31,30,24,25,24,26,25,24,27,26,25,24,28,27,26,25,24,29,28,27,26,25,24,18,19,18,20,19,18,21,20,
19,18,22,21,20,19,18,23,22,21,20,19,18,12,13,12,14,13,12,15,14,13,12,16,15,14,13,12,17,16,15,14,13,12,6,7,6,8,7,6,9,8,7,6,10,9,8,7,6,11,
10,9,8,7,6,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,0,1,
0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,0,0,1,0,1,2,0,1,2,3,0,
1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,12,12,13,12,13,14,12,13,14,15,12,13,14,15,16,12,13,14,15,
16,17,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,12,12,13,12,13,14,
12,13,14,15,12,13,14,15,16,12,13,14,15,16,17,18,18,19,18,19,20,18,19,20,21,18,19,20,21,22,18,19,20,21,22,23,0,0,1,0,1,2,0,1,2,3,0,1,2,3,
4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,12,12,13,12,13,14,12,13,14,15,12,13,14,15,16,12,13,14,15,16,17,18,
18,19,18,19,20,18,19,20,21,18,19,20,21,22,18,19,20,21,22,23,24,24,25,24,25,26,24,25,26,27,24,25,26,27,28,24,25,26,27,28,29,0,0,1,0,1,2,0,1,2,
3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,8,9,10,6,7,8,9,10,11,12,12,13,12,13,14,12,13,14,15,12,13,14,15,16,12,13,
14,15,16,17,18,18,19,18,19,20,18,19,20,21,18,19,20,21,22,18,19,20,21,22,23,24,24,25,24,25,26,24,25,26,27,24,25,26,27,28,24,25,26,27,28,29,30,30,31,30,
31,32,30,31,32,33,30,31,32,33,34,30,31,32,33,34,35,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,6,6,7,6,7,8,6,7,8,9,6,7,
8,9,10,6,7,8,9,10,11,12,12,13,12,13,14,12,13,14,15,12,13,14,15,16,12,13,14,15,16,17,18,18,19,18,19,20,18,19,20,21,18,19,20,21,22,18,19,20,21,22,
23,24,24,25,24,25,26,24,25,26,27,24,25,26,27,28,24,25,26,27,28,29,30,30,31,30,31,32,30,31,32,33,30,31,32,33,34,30,31,32,33,34,35,36,36,37,36,37,38,36,
37,38,39,36,37,38,39,40,36,37,38,39,40,41,
// (6, 0)
6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,
5,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,
// (6, 1)
13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,
0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,
4,3,2,1,0,6,5,4,3,2,1,0,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,
4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,0,0,1,0,
1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,
12,13,
// (6, 2)
20,19,19,18,18,18,17,17,17,17,16,16,16,16,16,15,15,15,15,15,15,14,14,14,14,14,14,14,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,
7,7,7,7,7,7,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,
1,1,1,1,1,0,0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,
2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,7,8,7,9,
8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,
1,0,14,15,14,16,15,14,17,16,15,14,18,17,16,15,14,19,18,17,16,15,14,20,19,18,17,16,15,14,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,
7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,
4,0,1,2,3,4,5,0,1,2,3,4,5,6,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,
9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,12,13,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,
8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,12,13,14,14,15,14,15,16,14,15,16,17,14,15,16,17,18,14,15,16,17,18,19,14,15,16,
17,18,19,20,
// (6, 3)
27,26,26,25,25,25,24,24,24,24,23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,21,21,20,19,19,18,18,18,17,17,17,17,16,16,16,16,16,15,15,15,15,15,15,14,
14,14,14,14,14,14,20,19,19,18,18,18,17,17,17,17,16,16,16,16,16,15,15,15,15,15,15,14,14,14,14,14,14,14,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,
8,8,8,8,8,7,7,7,7,7,7,7,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,13,12,12,11,11,11,10,10,10,10,
9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,6,5,5,4,
4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,
0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,
0,6,5,4,3,2,1,0,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,
0,5,4,3,2,1,0,6,5,4,3,2,1,0,14,15,14,16,15,14,17,16,15,14,18,17,16,15,14,19,18,17,16,15,14,20,19,18,17,16,15,14,7,8,7,9,8,7,10,9,
8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,21,22,
21,23,22,21,24,23,22,21,25,24,23,22,21,26,25,24,23,22,21,27,26,25,24,23,22,21,14,15,14,16,15,14,17,16,15,14,18,17,16,15,14,19,18,17,16,15,14,20,19,18,
17,16,15,14,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,
2,1,0,6,5,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,0,0,1,0,1,2,0,1,2,3,0,1,
2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,12,13,0,0,1,0,1,2,
0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,12,13,
14,14,15,14,15,16,14,15,16,17,14,15,16,17,18,14,15,16,17,18,19,14,15,16,17,18,19,20,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,
1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,12,13,14,14,15,14,15,16,14,15,16,17,14,15,16,17,18,14,
15,16,17,18,19,14,15,16,17,18,19,20,21,21,22,21,22,23,21,22,23,24,21,22,23,24,25,21,22,23,24,25,26,21,22,23,24,25,26,27,
// (6, 4)
34,33,33,32,32,32,31,31,31,31,30,30,30,30,30,29,29,29,29,29,29,28,28,28,28,28,28,28,27,26,26,25,25,25,24,24,24,24,23,23,23,23,23,22,22,22,22,22,22,21,
21,21,21,21,21,21,27,26,26,25,25,25,24,24,24,24,23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,21,21,20,19,19,18,18,18,17,17,17,17,16,16,16,16,16,15,
15,15,15,15,15,14,14,14,14,14,14,14,20,19,19,18,18,18,17,17,17,17,16,16,16,16,16,15,15,15,15,15,15,14,14,14,14,14,14,14,20,19,19,18,18,18,17,17,17,17,
16,16,16,16,16,15,15,15,15,15,15,14,14,14,14,14,14,14,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,13,12,12,11,
11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,
7,7,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,
1,0,0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,
2,1,1,1,1,1,1,0,0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,6,5,5,4,4,4,3,3,
3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,7,8,
7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,
3,2,1,0,14,15,14,16,15,14,17,16,15,14,18,17,16,15,14,19,18,17,16,15,14,20,19,18,17,16,15,14,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,
9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,21,22,21,23,22,21,24,23,22,21,25,24,
23,22,21,26,25,24,23,22,21,27,26,25,24,23,22,21,14,15,14,16,15,14,17,16,15,14,18,17,16,15,14,19,18,17,16,15,14,20,19,18,17,16,15,14,7,8,7,9,8,7,
10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,
28,29,28,30,29,28,31,30,29,28,32,31,30,29,28,33,32,31,30,29,28,34,33,32,31,30,29,28,21,22,21,23,22,21,24,23,22,21,25,24,23,22,21,26,25,24,23,22,21,27,
26,25,24,23,22,21,14,15,14,16,15,14,17,16,15,14,18,17,16,15,14,19,18,17,16,15,14,20,19,18,17,16,15,14,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,
11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,
0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,
8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,12,13,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,
5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,12,13,14,14,15,14,15,16,14,15,16,17,14,15,16,17,18,14,15,16,17,18,
19,14,15,16,17,18,19,20,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,
11,7,8,9,10,11,12,7,8,9,10,11,12,13,14,14,15,14,15,16,14,15,16,17,14,15,16,17,18,14,15,16,17,18,19,14,15,16,17,18,19,20,21,21,22,21,22,23,21,22,
23,24,21,22,23,24,25,21,22,23,24,25,26,21,22,23,24,25,26,27,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,
8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,12,13,14,14,15,14,15,16,14,15,16,17,14,15,16,17,18,14,15,16,17,18,19,14,15,16,
17,18,19,20,21,21,22,21,22,23,21,22,23,24,21,22,23,24,25,21,22,23,24,25,26,21,22,23,24,25,26,27,28,28,29,28,29,30,28,29,30,31,28,29,30,31,32,28,29,30,
31,32,33,28,29,30,31,32,33,34,
// (6, 5)
41,40,40,39,39,39,38,38,38,38,37,37,37,37,37,36,36,36,36,36,36,35,35,35,35,35,35,35,34,33,33,32,32,32,31,31,31,31,30,30,30,30,30,29,29,29,29,29,29,28,
28,28,28,28,28,28,34,33,33,32,32,32,31,31,31,31,30,30,30,30,30,29,29,29,29,29,29,28,28,28,28,28,28,28,27,26,26,25,25,25,24,24,24,24,23,23,23,23,23,22,
22,22,22,22,22,21,21,21,21,21,21,21,27,26,26,25,25,25,24,24,24,24,23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,21,21,27,26,26,25,25,25,24,24,24,24,
23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,21,21,20,19,19,18,18,18,17,17,17,17,16,16,16,16,16,15,15,15,15,15,15,14,14,14,14,14,14,14,20,19,19,18,
18,18,17,17,17,17,16,16,16,16,16,15,15,15,15,15,15,14,14,14,14,14,14,14,20,19,19,18,18,18,17,17,17,17,16,16,16,16,16,15,15,15,15,15,15,14,14,14,14,14,
14,14,20,19,19,18,18,18,17,17,17,17,16,16,16,16,16,15,15,15,15,15,15,14,14,14,14,14,14,14,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,
8,7,7,7,7,7,7,7,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,13,12,12,11,11,11,10,10,10,10,9,9,9,9,
9,8,8,8,8,8,8,7,7,7,7,7,7,7,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,13,12,12,11,11,11,10,10,
10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,6,5,
5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,
0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,
1,1,1,0,0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,
2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,
3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,14,15,14,16,15,14,17,16,15,14,18,17,16,15,14,19,18,17,16,15,14,20,19,18,17,16,15,14,
7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,
5,4,3,2,1,0,21,22,21,23,22,21,24,23,22,21,25,24,23,22,21,26,25,24,23,22,21,27,26,25,24,23,22,21,14,15,14,16,15,14,17,16,15,14,18,17,16,15,14,19,
18,17,16,15,14,20,19,18,17,16,15,14,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,
4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,28,29,28,30,29,28,31,30,29,28,32,31,30,29,28,33,32,31,30,29,28,34,33,32,31,30,29,28,21,22,21,23,
22,21,24,23,22,21,25,24,23,22,21,26,25,24,23,22,21,27,26,25,24,23,22,21,14,15,14,16,15,14,17,16,15,14,18,17,16,15,14,19,18,17,16,15,14,20,19,18,17,16,
15,14,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,
0,6,5,4,3,2,1,0,35,36,35,37,36,35,38,37,36,35,39,38,37,36,35,40,39,38,37,36,35,41,40,39,38,37,36,35,28,29,28,30,29,28,31,30,29,28,32,31,30,29,
28,33,32,31,30,29,28,34,33,32,31,30,29,28,21,22,21,23,22,21,24,23,22,21,25,24,23,22,21,26,25,24,23,22,21,27,26,25,24,23,22,21,14,15,14,16,15,14,17,16,
15,14,18,17,16,15,14,19,18,17,16,15,14,20,19,18,17,16,15,14,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,
0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,
3,4,5,6,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,
10,11,12,7,8,9,10,11,12,13,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,
9,10,11,7,8,9,10,11,12,7,8,9,10,11,12,13,14,14,15,14,15,16,14,15,16,17,14,15,16,17,18,14,15,16,17,18,19,14,15,16,17,18,19,20,0,0,1,0,1,2,
0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,12,13,
14,14,15,14,15,16,14,15,16,17,14,15,16,17,18,14,15,16,17,18,19,14,15,16,17,18,19,20,21,21,22,21,22,23,21,22,23,24,21,22,23,24,25,21,22,23,24,25,26,21,
22,23,24,25,26,27,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,
8,9,10,11,12,7,8,9,10,11,12,13,14,14,15,14,15,16,14,15,16,17,14,15,16,17,18,14,15,16,17,18,19,14,15,16,17,18,19,20,21,21,22,21,22,23,21,22,23,24,
21,22,23,24,25,21,22,23,24,25,26,21,22,23,24,25,26,27,28,28,29,28,29,30,28,29,30,31,28,29,30,31,32,28,29,30,31,32,33,28,29,30,31,32,33,34,0,0,1,0,
1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,
12,13,14,14,15,14,15,16,14,15,16,17,14,15,16,17,18,14,15,16,17,18,19,14,15,16,17,18,19,20,21,21,22,21,22,23,21,22,23,24,21,22,23,24,25,21,22,23,24,25,
26,21,22,23,24,25,26,27,28,28,29,28,29,30,28,29,30,31,28,29,30,31,32,28,29,30,31,32,33,28,29,30,31,32,33,34,35,35,36,35,36,37,35,36,37,38,35,36,37,38,
39,35,36,37,38,39,40,35,36,37,38,39,40,41,
// (6, 6)
48,47,47,46,46,46,45,45,45,45,44,44,44,44,44,43,43,43,43,43,43,42,42,42,42,42,42,42,41,40,40,39,39,39,38,38,38,38,37,37,37,37,37,36,36,36,36,36,36,35,
35,35,35,35,35,35,41,40,40,39,39,39,38,38,38,38,37,37,37,37,37,36,36,36,36,36,36,35,35,35,35,35,35,35,34,33,33,32,32,32,31,31,31,31,30,30,30,30,30,29,
29,29,29,29,29,28,28,28,28,28,28,28,34,33,33,32,32,32,31,31,31,31,30,30,30,30,30,29,29,29,29,29,29,28,28,28,28,28,28,28,34,33,33,32,32,32,31,31,31,31,
30,30,30,30,30,29,29,29,29,29,29,28,28,28,28,28,28,28,27,26,26,25,25,25,24,24,24,24,23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,21,21,27,26,26,25,
25,25,24,24,24,24,23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,21,21,27,26,26,25,25,25,24,24,24,24,23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,
21,21,27,26,26,25,25,25,24,24,24,24,23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,21,21,20,19,19,18,18,18,17,17,17,17,16,16,16,16,16,15,15,15,15,15,
15,14,14,14,14,14,14,14,20,19,19,18,18,18,17,17,17,17,16,16,16,16,16,15,15,15,15,15,15,14,14,14,14,14,14,14,20,19,19,18,18,18,17,17,17,17,16,16,16,16,
16,15,15,15,15,15,15,14,14,14,14,14,14,14,20,19,19,18,18,18,17,17,17,17,16,16,16,16,16,15,15,15,15,15,15,14,14,14,14,14,14,14,20,19,19,18,18,18,17,17,
17,17,16,16,16,16,16,15,15,15,15,15,15,14,14,14,14,14,14,14,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,13,12,
12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,
7,7,7,7,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,
8,8,8,7,7,7,7,7,7,7,13,12,12,11,11,11,10,10,10,10,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,6,5,5,4,4,4,3,3,3,3,2,2,
2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,6,5,5,4,4,4,
3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,
6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,
0,0,0,0,0,0,6,5,5,4,4,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,
4,3,2,1,0,6,5,4,3,2,1,0,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,
4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,14,15,14,16,15,14,17,16,15,14,18,17,16,15,14,19,18,17,16,15,14,20,19,18,17,16,15,14,7,8,7,9,
8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,
1,0,21,22,21,23,22,21,24,23,22,21,25,24,23,22,21,26,25,24,23,22,21,27,26,25,24,23,22,21,14,15,14,16,15,14,17,16,15,14,18,17,16,15,14,19,18,17,16,15,
14,20,19,18,17,16,15,14,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,
0,5,4,3,2,1,0,6,5,4,3,2,1,0,28,29,28,30,29,28,31,30,29,28,32,31,30,29,28,33,32,31,30,29,28,34,33,32,31,30,29,28,21,22,21,23,22,21,24,23,
22,21,25,24,23,22,21,26,25,24,23,22,21,27,26,25,24,23,22,21,14,15,14,16,15,14,17,16,15,14,18,17,16,15,14,19,18,17,16,15,14,20,19,18,17,16,15,14,7,8,
7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,
3,2,1,0,35,36,35,37,36,35,38,37,36,35,39,38,37,36,35,40,39,38,37,36,35,41,40,39,38,37,36,35,28,29,28,30,29,28,31,30,29,28,32,31,30,29,28,33,32,31,
30,29,28,34,33,32,31,30,29,28,21,22,21,23,22,21,24,23,22,21,25,24,23,22,21,26,25,24,23,22,21,27,26,25,24,23,22,21,14,15,14,16,15,14,17,16,15,14,18,17,
16,15,14,19,18,17,16,15,14,20,19,18,17,16,15,14,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,
3,2,1,0,4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,42,43,42,44,43,42,45,44,43,42,46,45,44,43,42,47,46,45,44,43,42,48,47,46,45,44,43,42,
35,36,35,37,36,35,38,37,36,35,39,38,37,36,35,40,39,38,37,36,35,41,40,39,38,37,36,35,28,29,28,30,29,28,31,30,29,28,32,31,30,29,28,33,32,31,30,29,28,34,
33,32,31,30,29,28,21,22,21,23,22,21,24,23,22,21,25,24,23,22,21,26,25,24,23,22,21,27,26,25,24,23,22,21,14,15,14,16,15,14,17,16,15,14,18,17,16,15,14,19,
18,17,16,15,14,20,19,18,17,16,15,14,7,8,7,9,8,7,10,9,8,7,11,10,9,8,7,12,11,10,9,8,7,13,12,11,10,9,8,7,0,1,0,2,1,0,3,2,1,0,
4,3,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1,0,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,0,0,1,0,
1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,
12,13,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,
12,7,8,9,10,11,12,13,14,14,15,14,15,16,14,15,16,17,14,15,16,17,18,14,15,16,17,18,19,14,15,16,17,18,19,20,0,0,1,0,1,2,0,1,2,3,0,1,2,3,
4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,12,13,14,14,15,14,15,16,14,15,
16,17,14,15,16,17,18,14,15,16,17,18,19,14,15,16,17,18,19,20,21,21,22,21,22,23,21,22,23,24,21,22,23,24,25,21,22,23,24,25,26,21,22,23,24,25,26,27,0,0,
1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,
10,11,12,13,14,14,15,14,15,16,14,15,16,17,14,15,16,17,18,14,15,16,17,18,19,14,15,16,17,18,19,20,21,21,22,21,22,23,21,22,23,24,21,22,23,24,25,21,22,23,
24,25,26,21,22,23,24,25,26,27,28,28,29,28,29,30,28,29,30,31,28,29,30,31,32,28,29,30,31,32,33,28,29,30,31,32,33,34,0,0,1,0,1,2,0,1,2,3,0,1,
2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,8,9,10,11,12,7,8,9,10,11,12,13,14,14,15,14,15,16,
14,15,16,17,14,15,16,17,18,14,15,16,17,18,19,14,15,16,17,18,19,20,21,21,22,21,22,23,21,22,23,24,21,22,23,24,25,21,22,23,24,25,26,21,22,23,24,25,26,27,
28,28,29,28,29,30,28,29,30,31,28,29,30,31,32,28,29,30,31,32,33,28,29,30,31,32,33,34,35,35,36,35,36,37,35,36,37,38,35,36,37,38,39,35,36,37,38,39,40,35,
36,37,38,39,40,41,0,0,1,0,1,2,0,1,2,3,0,1,2,3,4,0,1,2,3,4,5,0,1,2,3,4,5,6,7,7,8,7,8,9,7,8,9,10,7,8,9,10,11,7,
8,9,10,11,12,7,8,9,10,11,12,13,14,14,15,14,15,16,14,15,16,17,14,15,16,17,18,14,15,16,17,18,19,14,15,16,17,18,19,20,21,21,22,21,22,23,21,22,23,24,
21,22,23,24,25,21,22,23,24,25,26,21,22,23,24,25,26,27,28,28,29,28,29,30,28,29,30,31,28,29,30,31,32,28,29,30,31,32,33,28,29,30,31,32,33,34,35,35,36,35,
36,37,35,36,37,38,35,36,37,38,39,35,36,37,38,39,40,35,36,37,38,39,40,41,42,42,43,42,43,44,42,43,44,45,42,43,44,45,46,42,43,44,45,46,47,42,43,44,45,46,
47,48,
};
__constant__ int c_pair_offsets[L_AUX1*L_AUX1+1] = {
0, 3, 12, 30, 60, 105, 168,
252, 261, 288, 342, 432, 567, 756,
1008, 1026, 1080, 1188, 1368, 1638, 2016,
2520, 2550, 2640, 2820, 3120, 3570, 4200,
5040, 5085, 5220, 5490, 5940, 6615, 7560,
8820, 8883, 9072, 9450, 10080, 11025, 12348,
14112, 14196, 14448, 14952, 15792, 17052, 18816, 21168
};

extern __global__
void ft_aopair_kernel(double *out, PBCIntEnvVars envs, AFTBoundsInfo bounds,
                      int compressing);

extern __global__
void pbc_int3c2e_kernel(double *out, PBCIntEnvVars envs, PBCInt3c2eBounds bounds);
extern __global__
void pbc_int2c2e_kernel(double *out, PBCIntEnvVars envs, PBCInt2c2eBounds bounds);

int ft_ao_unrolled(double *out, PBCIntEnvVars *envs, AFTBoundsInfo *bounds,
                   int *scheme, int compressing);
int int3c2e_unrolled(double *out, PBCIntEnvVars *envs, PBCInt3c2eBounds *bounds);

extern "C" {
int build_ft_aopair(double *out, int compressing, PBCIntEnvVars *envs,
                    int *scheme, int *shls_slice, int npairs_ij, int ngrids,
                    int *bas_ij, double *grids, int *img_offsets, int *img_idx,
                    int *atm, int natm, int *bas, int nbas, double *env)
{
    int ish0 = shls_slice[0];
    int jsh0 = shls_slice[2];
    int li = bas[ANG_OF + ish0*BAS_SLOTS];
    int lj = bas[ANG_OF + jsh0*BAS_SLOTS];
    int iprim = bas[NPRIM_OF + ish0*BAS_SLOTS];
    int jprim = bas[NPRIM_OF + jsh0*BAS_SLOTS];
    int nfi = (li+1)*(li+2)/2;
    int nfj = (lj+1)*(lj+2)/2;
    int stride_i = 1;
    int stride_j = li + 1;
    // up to g functions
    int g_size = stride_j * (lj + 1);
    AFTBoundsInfo bounds = {li, lj, nfi, nfj, g_size,
        stride_i, stride_j, iprim, jprim,
        npairs_ij, ngrids, bas_ij, grids, img_offsets, img_idx};

    if (!ft_ao_unrolled(out, envs, &bounds, scheme, compressing)) {
        int nGv_per_block = scheme[0];
        int gout_stride = scheme[1];
        int nsp_per_block = scheme[2];
        dim3 threads(nGv_per_block, gout_stride, nsp_per_block);
        int sp_blocks = (npairs_ij + nsp_per_block - 1) / nsp_per_block;
        int Gv_batches = (ngrids + nGv_per_block - 1) / nGv_per_block;
        dim3 blocks(sp_blocks, Gv_batches);
        int buflen = g_size*6 * nGv_per_block * nsp_per_block;
        ft_aopair_kernel<<<blocks, threads, buflen*sizeof(double)>>>(
                out, *envs, bounds, compressing);
    }
    cudaError_t err = cudaGetLastError();
    if (err != cudaSuccess) {
        fprintf(stderr, "CUDA Error in ft_aopair_kernel: %s\n", cudaGetErrorString(err));
        return 1;
    }
    return 0;
}

int fill_int3c2e(double *out, PBCIntEnvVars *envs, int *scheme, int *shls_slice,
                 int naux, int n_prim_pairs, int n_ctr_pairs,
                 int *bas_ij_idx, int *pair_mapping, int *img_idx, uint32_t *img_offsets,
                 int *atm, int natm, int *bas, int nbas, double *env)
{
    int ish0 = shls_slice[0];
    int jsh0 = shls_slice[2];
    int ksh0 = shls_slice[4] + nbas;
    int ksh1 = shls_slice[5] + nbas;
    int nksh = ksh1 - ksh0;
    int li = bas[ANG_OF + ish0*BAS_SLOTS];
    int lj = bas[ANG_OF + jsh0*BAS_SLOTS];
    int lk = bas[ANG_OF + ksh0*BAS_SLOTS];
    int kprim = bas[NPRIM_OF + ksh0*BAS_SLOTS];
    int nfi = (li+1)*(li+2)/2;
    int nfj = (lj+1)*(lj+2)/2;
    int nfk = (lk+1)*(lk+2)/2;
    int nfij = nfi * nfj;
    int order = li + lj + lk;
    int nroots = order / 2 + 1;
    double omega = env[PTR_RANGE_OMEGA];
    if (omega < 0) { // SR ERIs
        nroots *= 2;
    }
    int stride_j = li + 1;
    int stride_k = stride_j * (lj + 1);
    // up to (gg|i)
    int g_size = stride_k * (lk + 1);
    PBCInt3c2eBounds bounds = {
        li, lj, lk, nroots, nfij, nfk, kprim,
        stride_j, stride_k, g_size, naux, nksh, ksh0,
        n_prim_pairs, n_ctr_pairs,
        bas_ij_idx, pair_mapping, img_offsets, img_idx
    };

    if (!int3c2e_unrolled(out, envs, &bounds)) {
        int nksh_per_block = scheme[0];
        int gout_stride = scheme[1];
        int nsp_per_block = scheme[2];
        dim3 threads(nksh_per_block, gout_stride, nsp_per_block);
        int tasks_per_block = SPTASKS_PER_BLOCK * nsp_per_block;
        int sp_blocks = (n_prim_pairs + tasks_per_block - 1) / tasks_per_block;
        int ksh_blocks = (nksh + nksh_per_block - 1) / nksh_per_block;
        dim3 blocks(sp_blocks, ksh_blocks);
        int buflen = (nroots*2+g_size*3+7) * (nksh_per_block * nsp_per_block) * sizeof(double);
        pbc_int3c2e_kernel<<<blocks, threads, buflen>>>(out, *envs, bounds);
    }
    cudaError_t err = cudaGetLastError();
    if (err != cudaSuccess) {
        fprintf(stderr, "CUDA Error in fill_int3c2e: %s\n", cudaGetErrorString(err));
        return 1;
    }
    return 0;
}

int fill_int2c2e(double *out, PBCIntEnvVars *envs, int shm_size,
                 int nbatches_shl_pair, int *bas_ij_idx,
                 int *shl_pair_offsets, int *gout_stride_lookup,
                 int *atm, int natm, int *bas, int nbas, double *env)
{
    PBCInt2c2eBounds bounds = {
        bas_ij_idx, shl_pair_offsets, gout_stride_lookup,
    };
    pbc_int2c2e_kernel<<<nbatches_shl_pair, THREADS, shm_size>>>(out, *envs, bounds);
    cudaError_t err = cudaGetLastError();
    if (err != cudaSuccess) {
        fprintf(stderr, "CUDA Error in int2c2e kernel: %s\n", cudaGetErrorString(err));
        return 1;
    }
    return 0;
}

int init_constant(int shm_size)
{
    cudaFuncSetAttribute(ft_aopair_kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, shm_size);
    cudaFuncSetAttribute(pbc_int3c2e_kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, shm_size);
    cudaFuncSetAttribute(pbc_int2c2e_kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, shm_size);
    cudaError_t err = cudaGetLastError();
    if (err != cudaSuccess) {
        fprintf(stderr, "Failed to set CUDA shm size %d: %s\n", shm_size,
                cudaGetErrorString(err));
        return 1;
    }
    return 0;
}
}
